import { BaseConnection, ConnectionStatus } from "tsrpc";
import { ClientConnection, gameServer } from "./server";
import { IUserInfo } from "./shared/gateClient/UserInfo";

declare module 'tsrpc' {
    export interface BaseConnection {
        userInfo: IUserInfo;
    }
}
type connAuthedHandler = (conn: ClientConnection) => void;

const allConnectionUserInfo: { [key: string]: IUserInfo } = {};
const allConnections: { [key: string]: ClientConnection } = {};
const connAuthedHandlers: connAuthedHandler[] = [];

/**
 * 初始化管理器,需要游戏服务启动后调用
 */
function initGameConnMgr(): void {
    //定义连接断开后的数据清理
    gameServer.flows.postDisconnectFlow.push(v => {
        delete allConnections[v.conn.connectionId];
        return v;
    });
    //定义授权
    gameServer.flows.preApiCallFlow.push(call => {
        let conf = call.service.conf;

        if (call.service.name == "Reconnect" || call.service.name == "Login") {
            return call;
        }

        if (!call.conn.userInfo) {
            call.error('You need login before do this', { code: 4000 });
            return undefined;
        }

        return call;
    })
}

function triggerConnAuthed(conn: ClientConnection) {
    //延时1毫秒,让原始授权流程完整走完后再触发事件
    setTimeout(() => {
        for (var i = 0; i < connAuthedHandlers.length; i++) {
            try {
                connAuthedHandlers[i](conn);
            } catch (e) {
                gameServer.logger?.error("triggerConnAuthed:", e);
            }
        }
    }, 1);
}
/**
 * 注册连接授权事件
 * @param handler 
 */
function onConnAuthed(handler: connAuthedHandler) {
    connAuthedHandlers.push(handler);
}
/**
 * 反注册连接授权事件
 * @param handler 
 */
function offConnAuthed(handler: connAuthedHandler) {
    connAuthedHandlers.remove(h => h == handler);
}

/**
 * 设置新连接通过授权认证
 * @param conn 
 * @param userInfo 
 */
function setConnAuthorized(conn: ClientConnection, userInfo: IUserInfo): void {
    conn.userInfo = userInfo;
    allConnections[conn.connectionId] = conn;
    allConnectionUserInfo[conn.connectionId] = userInfo;
    triggerConnAuthed(conn);
}
/**
 * 连接重连
 * @param conn 
 * @param oldSessionId 
 * @returns reconnect 
 */
function connReconnect(conn: ClientConnection, oldSessionId: string): string | null {
    var oldUserInfo = allConnectionUserInfo[oldSessionId];
    if (!oldUserInfo) return '连接不存在!';
    delete allConnectionUserInfo[oldSessionId];
    setConnAuthorized(conn, oldUserInfo);
    return null;
}
/**
 * 根据连接ID获取客户端连接对象
 * @param connectionId 
 * @returns
 */
function getConnById(connectionId: string): BaseConnection {
    return allConnections[connectionId];
}


export {
    initGameConnMgr,

    setConnAuthorized,
    getConnById,
    connReconnect,

    connAuthedHandler,
    onConnAuthed,
    offConnAuthed
}